/*******************************************************************************
  * 文件：InverterCtrl.h
  * 作者：djy
  * 版本：v1.0.0
  * 日期：2022-03-01
  * 说明：变频微波控制模块
*******************************************************************************/
#include "InverterCtrl.h"
#include "Hardware_Timer.h"
#include "Hardware_IO.h"
#include "Hardware.h"

/* 宏定义 *********************************************************************/
/* 类型定义 *******************************************************************/
typedef struct
{
    U16  u16HighLevelDuration;    // 高电平持续时间
    U8   u8PulseNums;             // 脉冲数目
    Bool bLastOSCState;           // 上次OSC电平
    Bool bDetectStart;            // 启动检测标志位
}Motive2Detect_ts;  // Motive2检测信息

typedef struct
{
    U16  u16HighLevelDuration;    // 高电平持续时间
    U16  u16LowLevelDuration;     // 低电平持续时间
    U8   u8PulseNums;             // 脉冲数目
    U8   u8InterruptCnt;          // 中断次数（500us）
    Bool bLastOSCState;           // 上次OSC电平
    Bool bDetectStart;            // 启动检测标志位
}RunDetect_ts; // Run检测信息

/* 变量定义 *******************************************************************/
static volatile InverterCtrl_ts sInverterCtrl;
static volatile Motive2Detect_ts sMotive2Detec;
static volatile RunDetect_ts sRunDetect;
/* 函数声明 *******************************************************************/
/* 函数定义 *******************************************************************/

/*******************************************************************************
  * 函数名：Inverter_ErrorHandler
  * 功  能：变频器-Error状态处理
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
static U32 Inverter_ErrorHandler(void)
{
    // 清空占空比
    sInverterCtrl.u8Duty = 0;

    // 占空比输出0
    Hardware_CH7_PWMChangeDuty(0);
    
    // 保持此状态
    return STATE_CTRL_HOLD;
}

/*******************************************************************************
  * 函数名：Inverter_RunHandler
  * 功  能：变频器-Run状态处理
  * 参  数：无
  * 返回值：无
  * 说  明：Run状态下用户可以根据设定功率，修改占空比
*******************************************************************************/
static U32 Inverter_RunHandler(void)
{
    // 输出显示板写入的占空比
    Hardware_CH7_PWMChangeDuty(sInverterCtrl.u8Duty);

    // 进入临界区
    Hardware_EnterCritical();

    // 清空H90次数
    sInverterCtrl.u8ErrorH90Times = 0;
    
    // 复位检测信息，启动OSC检测
    sRunDetect.u16HighLevelDuration = 0;
    sRunDetect.u16LowLevelDuration  = 0;
    sRunDetect.u8InterruptCnt = 0;
    sRunDetect.u8PulseNums  = 0;
    sRunDetect.bLastOSCState= Hardware_GetInverterOSC();
    sRunDetect.bDetectStart = ON;

    // 退出临界区
    Hardware_ExitCritical();

    // 保持此状态
    return STATE_CTRL_HOLD;
}

/*******************************************************************************
  * 函数名：Inverter_Motive2Handler
  * 功  能：变频器-Motive2状态处理
  * 参  数：无
  * 返回值：无
  * 说  明：1.该阶段输出固定占空比波形，重试7次，每次1S；
  *        2.同时在500us定时器中检测OSC信号，若有超过200ms高电平出现，则重启（H97）
  *        3.重试第七次后，若没检测到OSC脉冲，则重启(H98)
*******************************************************************************/
static U32 Inverter_Motive2Handler(void)
{
    // 第一次运行Motive2状态
    if(StateMachine_GetRetryCount((StateMachine_ts *)(StateMachine_ts *)&sInverterCtrl.sInverterSM) == 0)
    {
        // 输出固定占空比
        Hardware_CH7_PWMChangeDuty(U8_INVERTER_MOTIVE_2_DUTY);

        // 进入临界区
        Hardware_EnterCritical();
        
        // 复位检测信息，启动OSC检测
        sMotive2Detec.u16HighLevelDuration = 0;
        sMotive2Detec.u8PulseNums  = 0;
        sMotive2Detec.bLastOSCState= LOW;
        sMotive2Detec.bDetectStart = ON;

        // 退出临界区
        Hardware_ExitCritical();
    }

    // 重试7次
    if(StateMachine_GetRetryCount((StateMachine_ts *)&sInverterCtrl.sInverterSM) >= 7)
    {
        // 7S时间到
        if(sMotive2Detec.u8PulseNums == 0)
        {
            // 在7S内没检测到脉冲数，H98故障次数累加
            sInverterCtrl.u8ErrorH98Times++;

            if(sInverterCtrl.u8ErrorH98Times >= 3)
            {
                // H98已出现3次，置位故障码，切换至故障模式
                sInverterCtrl.uError.uError.u1ErrorH98 = 1;

                // 切换至故障模式
                StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_ERROR);
                
                return STATE_CTRL_HOLD;
            }
            else
            {
                // 切换至重试模式
                StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_INIT);
                
                return STATE_CTRL_HOLD;
            }
        }
        else
        {
            // 切换至下一状态
            return STATE_CTRL_NEXT;
        }
    }
    else
    {
        // 重试此状态
        return STATE_CTRL_RETRY;
    }
}

/*******************************************************************************
  * 函数名：Inverter_Motive1Handler
  * 功  能：变频器-Motive1状态处理
  * 参  数：无
  * 返回值：无
  * 说  明：在Motive1最后阶段，检测到OSC低电平方可切换至Motive2，否则重启(H95)；
*******************************************************************************/
static U32 Inverter_Motive1Handler(void)
{
    // 输出固定占空比，持续100ms
    Hardware_CH7_PWMChangeDuty(U8_INVERTER_MOTIVE_1_DUTY);
        
    // 根据本状态运行次数，选择是否进行状态切换
    if(StateMachine_GetRetryCount((StateMachine_ts *)&sInverterCtrl.sInverterSM) == 1)
    {
        // 是否检测到OSC低电平 （此处规格书要求检测到持续1ms低电平，待优化）
        if(Hardware_GetInverterOSC() == LOW)
        {
            // 检测到低电平，可以切换至下一状态
            return STATE_CTRL_NEXT;
        }
        else
        {
            // 未检测到低电平，H95出现次数自加
            sInverterCtrl.u8ErrorH95Times++;

            // 检查是否超过3次
            if(sInverterCtrl.u8ErrorH95Times >= 3)
            {
                // 已超过三次，置位H95故障
                sInverterCtrl.uError.uError.u1ErrorH95 = 1;

                // 切换至故障模式
                StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_ERROR);
            }
            else
            {
                // 未超过三次，重试
                StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_INIT);
            }
            
            return STATE_CTRL_HOLD;
        }
    }
    else
    {
        // 重试此状态（等待固定时间）
        return STATE_CTRL_RETRY;
    }
}

/*******************************************************************************
  * 函数名：Inverter_InitHandler
  * 功  能：变频器-初始化状态处理
  * 参  数：无
  * 返回值：无
  * 说  明：1.初始化状态定时100ms重试，重试5次;
  *        2.第4.5次时检测OSC是否为低电平异常;
*******************************************************************************/
static U32 Inverter_InitHandler(void)
{
    // 清零故障码和占空比
    sInverterCtrl.u8Duty = 0;
    sInverterCtrl.uError.u8Error = 0;

    // 占空比输出0
    Hardware_CH7_PWMChangeDuty(0);
    
    // 重试
    if(StateMachine_GetRetryCount((StateMachine_ts *)&sInverterCtrl.sInverterSM) <= 3)
    {
        // 重试三次
        return STATE_CTRL_RETRY;
    }
    else
    {
        // 查询OSC是否为低电平
        if(Hardware_GetInverterOSC() == LOW)
        {
            // OSC低电平认为异常H96
            sInverterCtrl.uError.uError.u1ErrorH96 = 1;
            
            // 切换至故障模式
            StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_ERROR);
            
            return STATE_CTRL_HOLD;
        }
        else
        {
            // OSC继续保持高电平，
            if(StateMachine_GetRetryCount((StateMachine_ts *)&sInverterCtrl.sInverterSM) == 4)
            {
                // 最后一次重试此状态
                return STATE_CTRL_RETRY;
            }
            else
            {
                // 切换至下一状态
                return STATE_CTRL_NEXT;
            }
        }
    }
}

/*******************************************************************************
  * 函数名：Inverter_OffHandler
  * 功  能：变频器-关闭状态处理
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
static U32 Inverter_OffHandler(void)
{
    sInverterCtrl.u8Duty = 0;
    sInverterCtrl.uError.u8Error = 0;
    sInverterCtrl.u8ErrorH90Times = 0;
    sInverterCtrl.u8ErrorH95Times= 0;
    sInverterCtrl.u8ErrorH96Times= 0;
    sInverterCtrl.u8ErrorH97Times= 0;
    sInverterCtrl.u8ErrorH98Times = 0;
    
    // 占空比输出0
    Hardware_CH7_PWMChangeDuty(0);

    // 保持此状态
    return STATE_CTRL_HOLD;
}

// 状态表  按照业务逻辑划分状态机
static const StateMachineOps_ts asInverterSMOpts[] =
{
    // 关闭---->初始化
    STATE_MACHINE_STATE(eINVERTER_OFF,          eINVERTER_INIT,         0,      Inverter_OffHandler          ),

    // 初始化---->Motive1
    STATE_MACHINE_STATE(eINVERTER_INIT,         eINVERTER_MOTIVE_1,     100,    Inverter_InitHandler         ),

    // Motive1---->Motive2
    STATE_MACHINE_STATE(eINVERTER_MOTIVE_1,     eINVERTER_MOTIVE_2,     100,    Inverter_Motive1Handler      ),

    // Motive2---->Run
    STATE_MACHINE_STATE(eINVERTER_MOTIVE_2,     eINVERTER_RUN,          1000,   Inverter_Motive2Handler      ),

    // Run---->关闭
    STATE_MACHINE_STATE(eINVERTER_RUN,          eINVERTER_OFF,          0,      Inverter_RunHandler          ),

    // 故障---->关闭
    STATE_MACHINE_STATE(eINVERTER_ERROR,        eINVERTER_OFF,          0,      Inverter_ErrorHandler        ),
};

/*******************************************************************************
  * 函数名：Inverter_GetError
  * 功  能：变频器-获取故障码
  * 参  数：无
  * 返回值：故障码
  * 说  明：无
*******************************************************************************/
U8 Inverter_GetError(void)
{
    return sInverterCtrl.uError.u8Error;
}

/*******************************************************************************
  * 函数名：Inverter_GetDuty
  * 功  能：变频器-获取占空比
  * 参  数：无
  * 返回值：占空比
  * 说  明：无
*******************************************************************************/
U8 Inverter_GetDuty(void)
{
    // 获取当前变频器状态
    InverterState_te eInverterState = (InverterState_te)StateMachine_GetCurState((StateMachine_ts *)&sInverterCtrl.sInverterSM);
    
    // 根据当前状态，返回当前工作的占空比
    if(eInverterState == eINVERTER_RUN)
    {
        return sInverterCtrl.u8Duty;
    }
    else if(eInverterState == eINVERTER_MOTIVE_1)
    {
        return U8_INVERTER_MOTIVE_1_DUTY;
    }
    else if(eInverterState == eINVERTER_MOTIVE_2)
    {
        return U8_INVERTER_MOTIVE_2_DUTY;
    }
    else
    {
        return 0;
    }
}

/*******************************************************************************
  * 函数名：Inverter_ChangeDuty
  * 功  能：变频器-修改占空比
  * 参  数：U8 u8Duty：占空比
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void Inverter_ChangeDuty(U8 u8Duty)
{
    // 获取当前变频器状态
    InverterState_te eInverterState = (InverterState_te)StateMachine_GetCurState((StateMachine_ts *)&sInverterCtrl.sInverterSM);
    
    // 根据当前状态，执行不同操作
    if(eInverterState == eINVERTER_OFF)
    {
        // 限幅
        if(u8Duty > U8_INVERTER_RUN_MAX_DUTY)
        {
            u8Duty = U8_INVERTER_RUN_MAX_DUTY;
        }

        // 限幅
        if(u8Duty < U8_INVERTER_RUN_MIN_DUTY)
        {
            u8Duty = U8_INVERTER_RUN_MIN_DUTY;
        }

        // 缓存占空比
        sInverterCtrl.u8Duty = u8Duty;

        // 关闭状态，切换为初始化，执行变频启动流程
        StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_INIT);
    }
    else if(eInverterState == eINVERTER_RUN)
    {
        if(u8Duty == 0)
        {
            // 关闭变频器
            StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_OFF);
        }
        else
        {
            // 限幅
            if(u8Duty > U8_INVERTER_RUN_MAX_DUTY)
            {
               u8Duty = U8_INVERTER_RUN_MAX_DUTY;
            }

            // 限幅
            if(u8Duty < U8_INVERTER_RUN_MIN_DUTY)
            {
                u8Duty = U8_INVERTER_RUN_MIN_DUTY;
            }
          
            // 缓存占空比
            sInverterCtrl.u8Duty = u8Duty;

            // 运行状态，直接更新占空比
            Hardware_CH7_PWMChangeDuty(sInverterCtrl.u8Duty);
        }
    }
}

/*******************************************************************************
  * 函数名：Inverter_TimerIntHandler
  * 功  能：变频器-500us定时器中断服务函数
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void Inverter_TimerIntHandler(void)
{
    // 获取当前变频器状态
    InverterState_te eInverterState = (InverterState_te)StateMachine_GetCurState((StateMachine_ts *)&sInverterCtrl.sInverterSM);

    // 根据当前状态，进行相关捕获
    switch(eInverterState)
    {
    case eINVERTER_MOTIVE_2:
        // 已启动OSC检测
        if(sMotive2Detec.bDetectStart == ON)
        {
            // 获取当前OSC电平
            Bool bOSCCurrentState = Hardware_GetInverterOSC();

            if(bOSCCurrentState == HIGH)
            {
                // 检查上次电平
                if(sMotive2Detec.bLastOSCState == LOW)
                {
                    // 若上次电平为低，则认为出现一个上升沿，脉冲数量自加
                    sMotive2Detec.u8PulseNums++;
                }
                else if(sMotive2Detec.bLastOSCState == HIGH)
                {
                    // 若上次电平也是高电平，高电平持续时间自加
                    sMotive2Detec.u16HighLevelDuration++;

                    // 检查高电平持续时间是否超过200ms = 400 * 0.5MS
                    if(sMotive2Detec.u16HighLevelDuration >= 400)
                    {
                        // H97出现次数增加
                        sInverterCtrl.u8ErrorH97Times++;

                        if(sInverterCtrl.u8ErrorH97Times >= 5)
                        {
                            // 置位H97故障码
                            sInverterCtrl.uError.uError.u1ErrorH97 = 1;

                            // 切换至故障
                            StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM, eINVERTER_ERROR);
                        }
                        else
                        {
                            // 切换到重试状态
                            StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM, eINVERTER_INIT);
                        }
                    }
                }
                
            }
            else if(bOSCCurrentState == LOW)
            {
                // 清空高电平持续时间
                sMotive2Detec.u16HighLevelDuration = 0;
            }
            
            // 保存当前状态
            sMotive2Detec.bLastOSCState = bOSCCurrentState;
        }
    break;
    case eINVERTER_RUN:
        // 已启动OSC检测
        if(sRunDetect.bDetectStart == ON)
        {
            // 获取当前OSC电平
            Bool bOSCCurrentState = Hardware_GetInverterOSC();

            // 检查当前电平
            if(bOSCCurrentState == HIGH)
            {
                // 当前电平为高，低电平持续时间清零
                sRunDetect.u16LowLevelDuration = 0;
                
                // 检查上次电平
                if(sRunDetect.bLastOSCState == LOW)
                {
                    // 上次电平为低电平，则认为出现一个上升沿，脉冲数目累加
                    sRunDetect.u8PulseNums++;
                }
                else if(sRunDetect.bLastOSCState == HIGH)
                {
                    // 上次电平也为高电平，则高电平持续时间累加
                    sRunDetect.u16HighLevelDuration++;

                    // 高电平持续时间超过200ms，H97故障次数累加
                    if(sRunDetect.u16HighLevelDuration >= 400)
                    {
                        // 清空高电平持续时间
                        sRunDetect.u16HighLevelDuration = 0;
                        
                        // H97次数累加
                        sInverterCtrl.u8ErrorH97Times++;

                        // H97出现次数达到5次，切换至故障模式
                        if(sInverterCtrl.u8ErrorH97Times >= 5)
                        {
                            // 置位H97故障
                            sInverterCtrl.uError.uError.u1ErrorH97 = 1;

                            // 切换至故障模式
                            StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_ERROR);
                        }
                        else
                        {
                            // 重试
                            StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_INIT);
                        }
                        
                    }
                }
            }
            else if(bOSCCurrentState == LOW)
            {
                // 高电平持续时间清零
                sRunDetect.u16HighLevelDuration = 0;

                // 检查上次电平状态
                if(sRunDetect.bLastOSCState == LOW)
                {
                    // 上次电平也为低电平，低电平持续时间累加
                    sRunDetect.u16LowLevelDuration++;

                    // 低电平持续时间超过200ms，H96出现次数累加
                    if(sRunDetect.u16LowLevelDuration >= 400)
                    {
                        // 清空低电平持续时间
                        sRunDetect.u16LowLevelDuration = 0;
                        
                        // H96次数累加
                        sInverterCtrl.u8ErrorH96Times++;

                        // H96出现次数超过超过3次，切换至故障
                        if(sInverterCtrl.u8ErrorH96Times >= 3)
                        {
                            // 置位H96故障码
                            sInverterCtrl.uError.uError.u1ErrorH96 = 1;

                            // 切换至故障
                            StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_ERROR);
                        }
                        else
                        {
                            // 重试
                            StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_INIT);
                        }
                    }
                }
            }

            // 中断次数累加
            sRunDetect.u8InterruptCnt++;

            // 中断次数达到72次，即500us*72=4*2TS = 36ms
            if(sRunDetect.u8InterruptCnt >= 72)
            {
                // 判断此时脉冲数
                if(sRunDetect.u8PulseNums < 4)
                {
                    // 脉冲数小于4，即代表OSC周期大于4倍正常周期（2TS），H90次数累加
                    sInverterCtrl.u8ErrorH90Times++;

                    // H90次数超过30次
                    if(sInverterCtrl.u8ErrorH90Times >= 30)
                    {
                        // 置位故障码
                        sInverterCtrl.uError.uError.u1ErrorH90 = 1;

                        // 切换至故障模式
                        StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_ERROR);
                    }
                }

                // 清空中断次数
                sRunDetect.u8InterruptCnt = 0;

                // 清空脉冲数
                sRunDetect.u8PulseNums = 0;
            }

            // 保存当前电平状态
            sRunDetect.bLastOSCState = bOSCCurrentState;
        }
    break;
    default:
    break;
    }
}
/*******************************************************************************
  * 函数名：Inverter_Init
  * 功  能：变频器-初始化
  * 参  数：无
  * 返回值：无
  * 说  明：无
*******************************************************************************/
void Inverter_Init(void)
{
    // 初始化状态机
    StateMchine_Init((StateMachine_ts *)&sInverterCtrl.sInverterSM,
                    "Inverter Ctrl SM", 
                    asInverterSMOpts, 
                    ARRAY_SIZE(asInverterSMOpts));

    // 上电默认关闭状态
    StateMachine_Change((StateMachine_ts *)&sInverterCtrl.sInverterSM,eINVERTER_OFF);
}
